/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.dusty.fs.filesystem.data;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.util.Date;
import ru.dusty.fs.filesystem.utils.PrimitiveSizes;
import static ru.dusty.fs.filesystem.utils.PrimitiveSizes.*;
import ru.dusty.fs.filesystem.utils.Utils;

/**
 *
 * @author vadim
 */
public class MetaData implements Serializable {
    
    private char[] name;
    
    private Date lastUpdDate;
    
    private BlockType type;
    
    private int size;
    
    private long blockSize = Utils.BLOCK_MIN_SIZE;
    
    private int blockCount = 1;
    
    public MetaData() {
        name = new char[10];
        lastUpdDate = new Date();
        type = BlockType.FILE;
        size = 0;
    }

    public Date getLastUpdDate() {
        return lastUpdDate;
    }

    public String getName() {
        StringBuilder str = new StringBuilder();
        
        for (char ch: name) {
            if (ch == 0) return str.toString();
            else {
                str.append(ch);
            }
        }
        
        return str.toString();
    }

    public BlockType getType() {
        return type;
    }
    
    public int getSize() {
        return size;
    }

    public void setLastUpdDate(Date lastUpdDate) {
        this.lastUpdDate = lastUpdDate;
    }

    public void setName(String name) {
        if (name == null) return;
        
        for (int i = 0; i < this.name.length; i++) {
            if (i >= name.length()) {
                this.name[i] = 0;
                return;
            } else {
                this.name[i] = name.charAt(i);
            }
        }
    }

    public void setType(BlockType type) {
        this.type = type;
    }
    
    public void setSize(int size) {
        this.size = size;
    }
    
    public void write(RandomAccessFile raf) throws IOException { 
        raf.writeByte(name.length);
        raf.writeChars(new String(name));
        
        long time = lastUpdDate.getTime();
        raf.writeLong(time);
        
        raf.writeByte(type.ordinal());
        
        raf.writeInt(size);
    }
    
    public void read(RandomAccessFile raf) throws IOException {
        int length = raf.readUnsignedByte();
        
        if (length > name.length || length < 0) throw new IOException("Incorrect length of the name.");
        
        for (int i = 0; i < length; i++) {
            name[i] = raf.readChar();
        }
        
        lastUpdDate = new Date(raf.readLong());
        
        BlockType[] values = BlockType.values();
        int typeByte = raf.readUnsignedByte();
        if (typeByte >= values.length || typeByte < 0) throw new IOException("Invalid block type.");
        type = values[typeByte];
        
        size = raf.readInt();
        blockSize = raf.length();
        updateBlocksCount();
    }
    
    public int getMetaDataSize() {
        return 1 + sizeof(name[0])*name.length + sizeof(lastUpdDate.getTime()) + 
                1 + sizeof(size);
    }
    
    private void updateBlocksCount() {
        int temp = 0;
        int sizeofInt = PrimitiveSizes.sizeof(temp);
        
        int allData;
        if (type.equals(BlockType.FILE)) {
            allData = getSize() + getMetaDataSize();
        } else {
            allData = sizeofInt * getSize() + getMetaDataSize();
        }
         
        int sizeInBlock = (int) (blockSize - sizeofInt);
        blockCount = allData / sizeInBlock;
        if (allData % sizeInBlock != 0) blockCount++;
    }

    public int getBlockCount() {
        return blockCount;
    }
    
}
